#include "specparaml.h"

#include "QtDebug.h"
#include "QtSerialization.h"

string SpecParamL::m_objname = "SpecParamL";
ExaFileObj SpecParamL::m_file_obj = EXA_FILE_OBJ_SPECPARAML;

SpecParamL::SpecParamL() :
    PKeyList(this)
{

}

SpecParamL::SpecParamL(const ExaTabRef& id_tab) :
    PKeyList(this,id_tab)
{

}

SpecParamL::~SpecParamL()
{
    m_erase();
}

bool SpecParamL::fromTr(const TempiRitornoL *tr, const SeismicGrid *sg)
{
    bool err = true;
    SpecParam sp(this);
    TempiRitorno tr_i(tr);
    int i, shift;
    shift = sizeOf();
    for (i = 0; i < tr->sizeOf(); ++i)
    {
        tr_i = tr->getAt(i);
        if (this->uniqueKey(tr_i.getKeyStr()))
        {
            // calcolo i parametri sismici col tempo di ritorno i-mo
            sg->site.specParamFromTr(tr_i,sp);

            // chiave e decrizione come il tempo di ritorno
            sp.setKeyStr(tr_i);
            sp.setDescr(tr_i.getDescr());

            // setto la chiave unica uguale al tempo di ritorno i-mo
            sp.setRefFrom(tr_i);
            this->insertAt(i+shift);
            this->valueAt(i+shift) = sp;
        }
        else
        {
            err = false;
        }
    }
    return err;
}

// Aggiorna i parametri spettrali ricalcolando sulla base di tr ed sg;
bool SpecParamL::fromTrUpdate(const TempiRitornoL *tr, const SeismicGrid *sg)
{
    int sp_i; // parametro spettrale corrente
    SpecParam sp_current;
    if (!sg->isComplete())
        return false;
    TempiRitorno tr_i; // tempo di ritorno corrente
    int i;
    for (sp_i = 0; sp_i < sizeOf(); ++sp_i)
    {
        sp_current = getAt(sp_i);
        if ( !sp_current.isCustom())
        {
            i = tr->findFirst(sp_current.getRefFrom(EXA_TAB_TEMPIRITORNO));
            if ( i != -1)
            {
                tr_i = tr->getAt(i);
                sg->site.specParamFromTr(tr_i,sp_current);
                valueAt(sp_i) = sp_current;
            }
        }
    }
    return true;
}

const SpecParam& SpecParamL::getAt(int i) const
{
    return( m_list.at(i) );
}

int SpecParamL::sizeOf(void) const
{
    return( m_list.size() );
}

SpecParam& SpecParamL::valueAt( int i )
{
    return( m_list[i] );
}

void  SpecParamL::remove( int i )
{
    removeRelatedAt(i);
    m_list.removeAt(i);
}

void  SpecParamL::insertAt( int i, int nb )
{
    int it;
    for ( it = 0; it < nb; it++)
    {
        SpecParam sp(this);
        m_list.insert( i+it,sp);
    }
}

void SpecParamL::reportMake( const string& objname ) const
{
    if (getReportCurrentStyle() == STYLE_VERBOSE)
    {
        int i;
        PReport::setReportStyle(STYLE_COMPACT);
        setReportOpt("N",false);
        for (i=0; i<sizeOf(); ++i)
        {
          getAt(i).reportMake();
        }
        resetReportStyle();
    }
    else if (getReportCurrentStyle() == STYLE_COMPACT)
    {

    }
    else if (getReportCurrentStyle() == STYLE_EXTENDED)
    {
        int i;
        PReport::setReportStyle(STYLE_COMPACT);
        setReportOpt("N",false);
        list <PKeyItem> pkey_list;
        list <PKeyItem> :: const_iterator it;
        PKeyItem i_key;
        for (i=0; i<sizeOf(); ++i)
        {
            getAt(i).reportMake();
            pkey_list = relatedAdiacentAt(i);

            for (it = pkey_list.begin(); it != pkey_list.end(); ++it)
            {
                i_key = *it;
                PReport::setReportStyle(STYLE_VERBOSE);
                i_key.reportMake();
            }
            PReport::setReportStyle(STYLE_COMPACT);
        }
        resetReportStyle();
    }
    else if (getReportCurrentStyle() == STYLE_JOURNAL)
    {
        addInLine(PKeyList::journal());
        moveLineInBlock(true);
    }
    setReportOpt("N",true);
    PReport::reportMake(m_objname);
}

bool SpecParamL::hasRefAt( int i, const PKeyItem& k ) const
{
    if ( getAt(i).nbRefFrom(k) != 0 )
        return true;
    else
        return false;
}

bool SpecParamL::setRefAt( int i, const PKeyItem& k )
{
    int err;
    valueAt(i).setRefFrom(k,err);
    if (err == 1)
        return true;
    else
        return false;
}

void SpecParamL::rename( int  i, const string& key, const string& descr)
{
    renameRelatedAt(i,key,descr);
    valueAt(i).setKeyStr(key);
    valueAt(i).setDescr(descr);
}

void SpecParamL::save ( void )
{
    m_list_cache = m_list;
}

void SpecParamL::restore ( void )
{
    m_list = m_list_cache;
}

ExaFileObj SpecParamL::fileObj ( void ) const
{
    return m_file_obj;
}

ExaFileErr SpecParamL::fileOpen (const string& file_name)
{
    ExaFileErr file_err;
    file_err = fileControl(file_name,EXA_FILE_OM_READ_ONLY);

    if ( file_err == EXA_FILE_ERR_OK )
    {
        quint32 magic_obj = fileMagic();
        switch (magic_obj)
        {
            case EXA_MN_1_0_0_BIN_SPD:
            {
                /**************************************************/
                /*           FILE BINARIO SLS V 100               */
                /**************************************************/
                // apro intestazione dati binari
                QFile file(QSTR(file_name));
                if (file.open(QIODevice::ReadOnly))
                {
                    QDataStream in(&file);
                    in.setVersion(QDataStream::Qt_4_5);
                    quint32 magic_file, version_file;
                    in >> magic_file >> version_file;

                    // elimino gli elementi della lista
                    this->removeAll();

                    // carico l'oggetto
                    in >> *this;
                }
                else
                {
                    return EXA_FILE_ERR_GENERIC;
                }
                /**************************************************/
            } break;
            default:
                return EXA_FILE_ERR_MN_UNKNOWN;
        }
    }
    fileReset();
    return file_err;
}

ExaFileErr SpecParamL::fileSave (const string& file_name) const
{
    ExaFileErr file_err;
    file_err = fileControl(file_name,EXA_FILE_OM_WRITE_ONLY);

    if ( file_err == EXA_FILE_ERR_OK )
    {
        quint32 magic_obj = fileMagic();
        quint32 version_obj = fileVersion();

        switch (magic_obj)
        {
            case EXA_MN_1_0_0_BIN_SPD:
            {
                /**************************************************/
                /*           FILE BINARIO SLS V 100               */
                /**************************************************/
                // apro intestazione dati binari
                QFile file(QSTR(file_name));
                if (file.open(QIODevice::WriteOnly))
                {
                    // salvo i dati binari
                    QDataStream out(&file);
                    out.setVersion(QDataStream::Qt_4_5);
                    out << magic_obj << version_obj << *this ;
                }
                else
                {
                    return EXA_FILE_ERR_GENERIC;
                }
                /**************************************************/
            } break;
            default:
                return EXA_FILE_ERR_MN_UNKNOWN;
        }
    }
    fileReset();
    return file_err;
}
